#include "widget_edit_gui.h"
#include "ui_widget_edit_gui.h"
#include "input/input_file.h"
#include "input/input_color.h"
#include "input/input_text.h"
#include "input/input_check.h"
#include "input/input_combo.h"
#include "../AvatarLibrary.h"
#include <QCheckBox>
#include <QPushButton>
#include <QMessageBox>
#include <QStack>

WidgetEditGui::WidgetEditGui(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::WidgetEditGui)
{
    ui->setupUi(this);
    ui->formLayout->setRowWrapPolicy(QFormLayout::WrapLongRows);
    ui->comboBoxType->addItems(QStringList{"button", "label", "trackbar", "editbox", "panel", "listview"});
    ui->comboBoxType->setCurrentIndex(-1);
    connect(ui->comboBoxType, &QComboBox::currentIndexChanged, this, [&](){ setupInput(ui->comboBoxType->currentText()); });
}

WidgetEditGui::~WidgetEditGui()
{
    delete ui;
}

/**
 * @brief 新增GUI
 */
void WidgetEditGui::newGui()
{
    loadAttributeMap();
    setupInput(ui->comboBoxType->currentText());
}

/**
 * @brief 根据类型创建属性列表
 * @param type
 * @param int
 */
void WidgetEditGui::setupInput(const QString &type)
{
    while (ui->formLayout->rowCount() > 2) ui->formLayout->removeRow(2);
    auto iter = _attributeMap.find(type);
    if (iter == _attributeMap.end()) return;
    int row = 1;
    foreach (auto item, iter.value())
    {
        if (item.type == GuiValueType::BOOLEAN) addRowCheck(row, item.label, item.name, item.value);
        else if (item.type == GuiValueType::INTEGER) addRowText(row, item.label, item.name, "int", item.value);
        else if (item.type == GuiValueType::FLOAT) addRowText(row, item.label, item.name, "float", item.value);
        else if (item.type == GuiValueType::STRING) addRowText(row, item.label, item.name, "string", item.value);
        else if (item.type == GuiValueType::COLOR) addRowColor(row, item.label, item.name, item.value);
        else if (item.type == GuiValueType::TEXTALIGN) addRowCombo(row, item.label, item.name, QStringList{ "left", "center", "right" }, nullptr, "string", item.value);
        else if (item.type == GuiValueType::TEXTARRAY) addRowText(row, item.label, item.name, "string", item.value);
        else if (item.type == GuiValueType::ALIGN) addRowCombo(row, item.label, item.name, QStringList{ "topleft", "topcenter", "topright", "middleleft", "middlecenter", "middleright", "bottomleft", "bottomcenter", "bottomright" }, nullptr, "string", item.value);
        else if (item.type == GuiValueType::DIRECTION) addRowCombo(row, item.label, item.name, QStringList{ "", "horizontal", "vertical" }, nullptr, "string", item.value);
        else if (item.type == GuiValueType::FILEPATH) addRowFile(row, item.label, item.name, "Image (*.jpg *.jpeg *.png *.bmp *.tga)", item.value);
        row++;
    }
    if (ui->lineEditName->text().isEmpty()) ui->lineEditName->setText(type + "_" + QString::number(_typeCountMap[type]));
    QPushButton* previewButton = new QPushButton(this);
    previewButton->setText("预览效果");
    ui->formLayout->addRow("", previewButton);
    connect(previewButton, &QPushButton::clicked, this, [=]() {
        QString type = ui->comboBoxType->currentText();
        QString name = ui->lineEditName->text();
        if (name.isEmpty()) QMessageBox::warning(this, "错误", QString("请输入%1").arg(ui->labelName->text()));
        else
        {
            QString desc;
            QString evt;
            getAttribute(type, name, desc, evt);
            AvatarLibrary::avatar_command(QString("gui.delete('%1')").arg(name));
            AvatarLibrary::avatar_command(QString("gui.create('%1', '%2', '%3')").arg(name, type, desc));
        }
    });
    QPushButton* confirmButton = new QPushButton(this);
    confirmButton->setText("确认添加");
    ui->formLayout->addRow("", confirmButton);
    connect(confirmButton, &QPushButton::clicked, this, [=]() {
        QString type = ui->comboBoxType->currentText();
        QString name = ui->lineEditName->text();
        if (name.isEmpty()) QMessageBox::warning(this, "错误", QString("请输入%1").arg(ui->labelName->text()));
        else
        {
            QString desc;
            QString evt;
            _typeCountMap[type] += 1;
            ui->lineEditName->setText(type + "_" + QString::number(_typeCountMap[type]));
            getAttribute(type, name, desc, evt);
            emit sig_editApply(type, name, desc, evt);
        }
    });
}

void WidgetEditGui::addRowCheck(int row, const QString& title, const QString& name, const QString& defValue)
{
    InputCheck* widget = new InputCheck(this, name);
    widget->setValue(defValue);
    int index = row + 2;
    while (index < ui->formLayout->rowCount())
    {
        if (dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(index, QFormLayout::FieldRole)->widget())) ui->formLayout->removeRow(index);
        else index++;
    }
    ui->formLayout->insertRow(row + 2, title, widget);
}

void WidgetEditGui::addRowColor(int row, const QString& title, const QString& name, const QString& defValue)
{
    InputColor* widget = new InputColor(this, name);
    widget->setValue(defValue);
    int index = row + 2;
    while (index < ui->formLayout->rowCount())
    {
        if (dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(index, QFormLayout::FieldRole)->widget())) ui->formLayout->removeRow(index);
        else index++;
    }
    ui->formLayout->insertRow(row + 2, title, widget);
}

void WidgetEditGui::addRowCombo(int row, const QString& title, const QString& name, const QStringList& items, std::function<void(int)> onChange, const QString& type, const QString& defValue)
{
    InputCombo* widget = new InputCombo(this, name);
    widget->setItems(items);
    widget->setType(type);
    widget->setCallback(onChange);
    widget->setValue(defValue);
    int index = row + 2;
    while (index < ui->formLayout->rowCount())
    {
        if (dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(index, QFormLayout::FieldRole)->widget())) ui->formLayout->removeRow(index);
        else index++;
    }
    ui->formLayout->insertRow(row + 2, title, widget);
}

void WidgetEditGui::addRowFile(int row, const QString& title, const QString& name, const QString& filter, const QString& defValue)
{
    InputFile* widget = new InputFile(this, name);
    widget->setFilter(filter);
    widget->setValue(defValue);
    int index = row + 2;
    while (index < ui->formLayout->rowCount())
    {
        if (dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(index, QFormLayout::FieldRole)->widget())) ui->formLayout->removeRow(index);
        else index++;
    }
    ui->formLayout->insertRow(row + 2, title, widget);
}

void WidgetEditGui::addRowText(int row, const QString& title, const QString& name, const QString& type, const QString& defValue)
{
    InputText* widget = new InputText(this, name);
    widget->setType(type);
    widget->setValue(defValue);
    int index = row + 2;
    while (index < ui->formLayout->rowCount())
    {
        if (dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(index, QFormLayout::FieldRole)->widget())) ui->formLayout->removeRow(index);
        else index++;
    }
    ui->formLayout->insertRow(row + 2, title, widget);
}

void WidgetEditGui::loadAttributeMap()
{
    if (!_attributeMap.empty()) return;
    QList<GuiAttribute> basic, button, label, trackbar, editbox, panel, listview;
    basic.append(GuiAttribute(GuiValueType::STRING, "父元素", "parent", ""));
    basic.append(GuiAttribute(GuiValueType::BOOLEAN, "可见性", "visible", "true"));
    basic.append(GuiAttribute(GuiValueType::ALIGN, "对齐方式", "align", "middlecenter"));
    basic.append(GuiAttribute(GuiValueType::INTEGER, "左边距", "left", "0"));
    basic.append(GuiAttribute(GuiValueType::INTEGER, "上边距", "top", "0"));
    button.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "100"));
    button.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "50"));
    button.append(GuiAttribute(GuiValueType::STRING, "字体", "font", "default"));
    button.append(GuiAttribute(GuiValueType::INTEGER, "字体大小", "fontSize", "16"));
    button.append(GuiAttribute(GuiValueType::STRING, "按钮文字", "text", "按钮"));
    button.append(GuiAttribute(GuiValueType::BOOLEAN, "拉伸平铺", "stretch", "false"));
    button.append(GuiAttribute(GuiValueType::FILEPATH, "按钮图片", "image", ""));
    button.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#00D660FF"));
    button.append(GuiAttribute(GuiValueType::COLOR, "文本颜色", "foreColor", "#FFFFFFFF"));
    button.append(GuiAttribute(GuiValueType::COLOR, "活动背景色", "backColorActive", "#00B97BFF"));
    button.append(GuiAttribute(GuiValueType::COLOR, "活动前景色", "foreColorActive", "#FFFFFFFF"));
    button.append(GuiAttribute(GuiValueType::INTEGER, "边框宽度", "borderWidth", "0"));
    button.append(GuiAttribute(GuiValueType::INTEGER, "圆角半径", "borderRadius", "0"));
    label.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "100"));
    label.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "28"));
    label.append(GuiAttribute(GuiValueType::STRING, "字体", "font", "default"));
    label.append(GuiAttribute(GuiValueType::INTEGER, "字体大小", "fontSize", "16"));
    label.append(GuiAttribute(GuiValueType::STRING, "文字", "text", "标签"));
    label.append(GuiAttribute(GuiValueType::BOOLEAN, "拉伸平铺", "stretch", "false"));
    label.append(GuiAttribute(GuiValueType::TEXTALIGN, "文字对齐", "textAlign", "left"));
    label.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#00000000"));
    label.append(GuiAttribute(GuiValueType::COLOR, "文本颜色", "foreColor", "#FFFFFFFF"));
    trackbar.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "200"));
    trackbar.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "24"));
    trackbar.append(GuiAttribute(GuiValueType::STRING, "字体", "font", "default"));
    trackbar.append(GuiAttribute(GuiValueType::INTEGER, "字体大小", "fontSize", "16"));
    trackbar.append(GuiAttribute(GuiValueType::BOOLEAN, "显示百分比", "percent", "false"));
    trackbar.append(GuiAttribute(GuiValueType::FLOAT, "当前值", "value", "0.0"));
    trackbar.append(GuiAttribute(GuiValueType::FLOAT, "最小值", "min", "0.0"));
    trackbar.append(GuiAttribute(GuiValueType::FLOAT, "最大值", "max", "100.0"));
    trackbar.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#E2E2E2A0"));
    trackbar.append(GuiAttribute(GuiValueType::COLOR, "前景颜色", "foreColor", "#00D660FF"));
    trackbar.append(GuiAttribute(GuiValueType::COLOR, "文本颜色", "textColor", "#F02400FF"));
    trackbar.append(GuiAttribute(GuiValueType::INTEGER, "边框宽度", "borderWidth", "0"));
    trackbar.append(GuiAttribute(GuiValueType::INTEGER, "圆角半径", "borderRadius", "0"));
    editbox.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "100"));
    editbox.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "32"));
    editbox.append(GuiAttribute(GuiValueType::STRING, "字体", "font", "default"));
    editbox.append(GuiAttribute(GuiValueType::INTEGER, "字体大小", "fontSize", "16"));
    editbox.append(GuiAttribute(GuiValueType::STRING, "文字", "text", ""));
    editbox.append(GuiAttribute(GuiValueType::TEXTALIGN, "文字对齐", "textAlign", "left"));
    editbox.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#FFFFFFFF"));
    editbox.append(GuiAttribute(GuiValueType::COLOR, "文本颜色", "foreColor", "#000000FF"));
    editbox.append(GuiAttribute(GuiValueType::INTEGER, "边框宽度", "borderWidth", "0"));
    editbox.append(GuiAttribute(GuiValueType::INTEGER, "圆角半径", "borderRadius", "0"));
    panel.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "200"));
    panel.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "200"));
    panel.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#FFFFFFFF"));
    panel.append(GuiAttribute(GuiValueType::COLOR, "前景颜色", "foreColor", "#000000FF"));
    panel.append(GuiAttribute(GuiValueType::INTEGER, "边框宽度", "borderWidth", "0"));
    panel.append(GuiAttribute(GuiValueType::INTEGER, "圆角半径", "borderRadius", "0"));
    panel.append(GuiAttribute(GuiValueType::DIRECTION, "布局方向", "flowDirection", ""));
    panel.append(GuiAttribute(GuiValueType::INTEGER, "子元素间距", "spacing", "2"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "宽度", "width", "100"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "高度", "height", "200"));
    listview.append(GuiAttribute(GuiValueType::STRING, "字体", "font", "default"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "字体大小", "fontSize", "16"));
    listview.append(GuiAttribute(GuiValueType::BOOLEAN, "显示分割线", "splitLine", "true"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "列表项高度", "itemHeight", "32"));
    listview.append(GuiAttribute(GuiValueType::TEXTARRAY, "列表项", "items", "项目1,项目2"));
    listview.append(GuiAttribute(GuiValueType::TEXTALIGN, "文字对齐", "textAlign", "center"));
    listview.append(GuiAttribute(GuiValueType::COLOR, "背景颜色", "backColor", "#00D660FF"));
    listview.append(GuiAttribute(GuiValueType::COLOR, "文本颜色", "foreColor", "#FFFFFFFF"));
    listview.append(GuiAttribute(GuiValueType::COLOR, "阴影颜色", "fadeColor", "#0B443BFF"));
    listview.append(GuiAttribute(GuiValueType::COLOR, "分割线颜色", "splitColor", "#FFFFFFFF"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "边框宽度", "borderWidth", "0"));
    listview.append(GuiAttribute(GuiValueType::INTEGER, "圆角半径", "borderRadius", "0"));
    _attributeMap["button"].append(basic);
    _attributeMap["button"].append(button);
    _attributeMap["label"].append(basic);
    _attributeMap["label"].append(label);
    _attributeMap["trackbar"].append(basic);
    _attributeMap["trackbar"].append(trackbar);
    _attributeMap["editbox"].append(basic);
    _attributeMap["editbox"].append(editbox);
    _attributeMap["panel"].append(basic);
    _attributeMap["panel"].append(panel);
    _attributeMap["listview"].append(basic);
    _attributeMap["listview"].append(listview);
}

void WidgetEditGui::getAttribute(const QString& type, const QString& name, QString& desc, QString& evt)
{
    QStringList attribute;
    for (int i = 2; i < ui->formLayout->rowCount() - 2; i++)
    {
        WidgetInput* widget = dynamic_cast<WidgetInput*>(ui->formLayout->itemAt(i, QFormLayout::FieldRole)->widget());
        if (!widget->isEmpty())
        {
            QString value = widget->getValue();
            while (value.startsWith('\'')) value.remove(0, 1);
            while (value.endsWith('\'')) value.remove(value.length() - 1, 1);
            attribute.append(widget->name() + "=" + value);
        }
    }
    desc = attribute.join(';');
    if (type == "button") {
        evt = "function(evt)\n\tif evt.event == gui.EVENT_CLICK then\n\t\t--TODO: 此处添加事件处理\n\tend\nend";
    } else if (type == "trackbar") {
        int minIdx = desc.indexOf("min=") + 4;
        int maxIdx = desc.indexOf("max=") + 4;
        int widthIdx = desc.indexOf("width=") + 6;
        evt = "function(evt)\n\tif evt.event == gui.EVENT_PRESS or evt.event == gui.EVENT_DRAG then\n\t\tlocal value = evt.x * (%3 - %2) / %4 + %2\n\t\tgui.modify('%1', 'value='..value)\n\t\t--TODO: 此处添加事件处理\n\tend\nend";
        evt = evt.arg(name, desc.mid(minIdx, desc.indexOf(";", minIdx) - minIdx), desc.mid(maxIdx, desc.indexOf(";", maxIdx) - maxIdx), desc.mid(widthIdx, desc.indexOf(";", widthIdx) - widthIdx));
    } else if (type == "editbox") {
        evt = "function(evt)\n\tif evt.event == gui.EVENT_KEY then\n\t\t--TODO: 此处添加事件处理\n\tend\nend";
    } else if (type == "listview") {
        evt = "function(evt)\n\tif evt.event == gui.EVENT_CLICK then\n\t\tlocal selectedIndex = tonumber(gui.attrib('%1', 'selectedIndex'))\n\t\t--TODO: 此处添加事件处理\n\tend\nend";
        evt = evt.arg(name);
    }
}
